﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SwimmingCompetition.AST;
using SwimmingCompetition.Exceptions;
using System.Windows.Forms;
using System.IO;
using System.Text.RegularExpressions;

namespace SwimmingCompetition.Visitors
{
    class HTMLVisitor : IEventVisitor
    {
        private EventObject _event;
        private TextWriter _htmlWriter;

        public HTMLVisitor(string fileName)
        {
            _htmlWriter = new StreamWriter("HTMLEvent.html");
            _event = new EventObject();
        }

        public void Visit(ABirthdayNode node)
        {
            ((LaneNode)node.Parent).Ath.Birthday = node.Text;
        }

        public void Visit(ACode node)
        {
            string urlRegex = @"[a-zA-Z]{3}[-][0-9]{6}";
            Regex validator = new Regex(urlRegex);
            string code = Utilities.RemoveQuotes(node.Text);
            if (validator.IsMatch(code))
            {
                ((LaneNode)node.Parent).Ath.Code = code;
            }
            else
            {
                _htmlWriter.Close();
                throw new ACodeException("EventiATappe.Exceptions.ACodeException", "Athele code " + node.Text + " not corrected!");
            }
        }

        public void Visit(ANameNode node)
        {
            ((LaneNode)node.Parent).Ath.Name = Utilities.RemoveQuotes(node.Text);
        }

        public void Visit(ASocietyNode node)
        {
            ((LaneNode)node.Parent).Ath.Society = Utilities.RemoveQuotes(node.Text);
        }

        public void Visit(ASurnameNode node)
        {
            ((LaneNode)node.Parent).Ath.Surname = Utilities.RemoveQuotes(node.Text);
        }

        public void Visit(ATimeRegNode node)
        {
            int mm = int.Parse(node.Text.Split(':')[0]);
            int ss = int.Parse(node.Text.Split(':')[1]);

            if (mm < 0 || mm > 59 || ss < 0 || ss > 59)
            {
                throw new ATimeException("EventiATappe.Exceptions.ATimeException", "Registration Time " + node.Text + " not corrected!");
            }
            ((LaneNode)node.Parent).Ath.TimeRegistry = node.Text;
        }

        public void Visit(ATimeResultNode node)
        {
            int mm = int.Parse(node.Text.Split(':')[0]);
            int ss = int.Parse(node.Text.Split(':')[1]);

            if (mm < 0 || mm > 59 || ss < 0 || ss > 59)
            {
                throw new ATimeException("EventiATappe.Exceptions.ATimeException", "Result Time " + node.Text + " not corrected!");
            }
            ((LaneNode)node.Parent).Ath.TimeResult = node.Text;
        }

        public void Visit(CategoryCompNode node)
        {
            ((SpecCompNode)node.Parent).Competition.Category = node.Text;
        }

        public void Visit(CategoryNode node)
        {
            _event.CategoryEvent = node.Text;
        }

        public void Visit(CoadjuctorNode node)
        {
            _event.Coadjuctor = Utilities.RemoveQuotes(node.Text);
        }

        public void Visit(CompEmployeeNode node)
        {
            _event.CompEmpl = Utilities.RemoveQuotes(node.Text);
        }

        public void Visit(CompNameNode node)
        {
            node.SSComp = new StartListSingleComp();
            node.SSComp.NameSingleComp = Utilities.RemoveQuotes(node.Text);
            foreach (ASTNode childNode in node.Children)
            {
                childNode.Accept(this);
            }
            _event.StartList.Add(node.SSComp);
        }

        public void Visit(CronoServiceNode node)
        {
            _event.CronoServ = Utilities.RemoveQuotes(node.Text);
        }

        public void Visit(CronoSocietyNode node)
        {
            _event.CronoSociety = Utilities.RemoveQuotes(node.Text);
        }

        public void Visit(CronoTypeNode node)
        {
            _event.CronoType = Utilities.RemoveQuotes(node.Text);
        }

        public void Visit(DateProgCompNode node)
        {
            node.dP = new DayProgram();
            node.dP.Date = node.Text;
            foreach (ASTNode childNode in node.Children)
            {
                childNode.Accept(this);
            }
            _event.ProgramList.Add(node.dP);
        }

        public void Visit(DepJudgeNode node)
        {
            _event.Depjudge = Utilities.RemoveQuotes(node.Text);
        }

        public void Visit(DoctorNode node)
        {
            _event.Doctor = Utilities.RemoveQuotes(node.Text);
        }

        public void Visit(EndDateRegNode node)
        {
            _event.EndReg = node.Text;
        }

        public void Visit(EndNode node)
        {
            _event.EndEv = node.Text;
        }

        public void Visit(FalseStartEmployeeNode node)
        {
            _event.FSEmpl = Utilities.RemoveQuotes(node.Text);
        }

        public void Visit(HourNode node)
        {
            int hh = int.Parse(node.Text.Split(':')[0]);
            int mm = int.Parse(node.Text.Split(':')[1]);

            if (hh > 24 || hh < 0 || mm < 0 || mm > 59)
            {
                _htmlWriter.Close();
                throw new TimeOutOfBoundsException("EventiATappe.Exceptions.TimeOutOfBoundsException", "Hour " + node.Text + " not corrected!");
            }

            ((SpecCompNode)node.Parent).Competition.Hour = node.Text;
        }

        public void Visit(LaneNode node)
        {
            node.Ath = new Athlete();
            node.Ath.Lane = node.Text;
            if (int.Parse(node.Ath.Lane) <= int.Parse(_event.Lanes))
            {
                foreach (ASTNode childNode in node.Children)
                {
                    childNode.Accept(this);
                }
                ((TurnCompNode)node.Parent).ST.Athlete.Add(node.Ath);
            }
            else
            {
                _htmlWriter.Close();
                throw new LaneOutOfBoundException("EventiATappe.Exceptions.LaneOutOfBoundException", "Lane " + node.Text + " not corrected!");
            }
        }

        public void Visit(LanesNode node)
        {
            _event.Lanes = node.Text;
        }

        public void Visit(LimitTimeRegNode node)
        {
            _event.LimitTime = Utilities.RemoveQuotes(node.Text);
        }

        public void Visit(LocationNode node)
        {
            _event.Location = Utilities.RemoveQuotes(node.Text);
        }

        public void Visit(ManagerNode node)
        {
            _event.Manager = Utilities.RemoveQuotes(node.Text);
        }

        public void Visit(NameCompetitionNode node)
        {
            _event.NameEvent = Utilities.RemoveQuotes(node.Text);
        }

        public void Visit(NoteNode node)
        {
            _event.Note = Utilities.RemoveQuotes(node.Text);
        }

        public void Visit(NumberTypeComp node)
        {
            ((TurnCompNode)node.Parent).ST.NumeberTurn = node.Text;
        }

        public void Visit(OrganizationNode node)
        {
            _event.Organization = Utilities.RemoveQuotes(node.Text);
        }

        public void Visit(PoolBaseNode node)
        {
            _event.PoolBase = node.Text;
        }

        public void Visit(RefereeNode node)
        {
            _event.Referee = Utilities.RemoveQuotes(node.Text);
        }

        public void Visit(SpeakerNode node)
        {
            _event.Speaker = Utilities.RemoveQuotes(node.Text);
        }

        public void Visit(SpecCompNode node)
        {
            node.Competition = new SingleCompetition();
            node.Competition.Spec = Utilities.RemoveQuotes(node.Text);
            foreach (ASTNode childNode in node.Children)
            {
                childNode.Accept(this);
            }
            ((DateProgCompNode)node.Parent).dP.CompetitionsOfDay.Add(node.Competition);
        }

        public void Visit(StartNode node)
        {
            _event.StartEv = node.Text;
        }

        public void Visit(TurnCompNode node)
        {
            if (node.Parent is SpecCompNode)
                ((SpecCompNode)node.Parent).Competition.Turn = node.Text;
            else
            {
                node.ST = new SingleTurn();
                node.ST.NameTurn = node.Text;
                foreach (ASTNode childNode in node.Children)
                {
                    childNode.Accept(this);
                }
                ((CompNameNode)node.Parent).SSComp.StartL.Add(node.ST);
            }
        }

        public void Visit(TypeNode node)
        {
            _event.Type = Utilities.RemoveQuotes(node.Text);
        }

        public void Visit(InfoEventNode node)
        {
            foreach (ASTNode childNode in node.Children)
            {
                childNode.Accept(this);
            }
        }


        public void Visit(EventNode node)
        {
            _htmlWriter.WriteLine("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">");
            _htmlWriter.WriteLine("<html xmlns=\"http://www.w3.org/1999/xhtml\">");
            _htmlWriter.WriteLine("<head>");
            _htmlWriter.WriteLine("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>");
            _htmlWriter.WriteLine(" <link href=\"table_design.css\" rel=\"stylesheet\" type=\"text/css\" />");
            
            foreach (ASTNode childNode in node.Children)
            {
                childNode.Accept(this);
            }

            _htmlWriter.WriteLine("<title>" + _event.NameEvent + "</title>");
            _htmlWriter.WriteLine("</head>");
            _htmlWriter.WriteLine("<body>");

            _htmlWriter.WriteLine("<div id=\"page\">");
            _htmlWriter.WriteLine("<div id=\"title\">" + _event.NameEvent + "</div>");

            _htmlWriter.WriteLine("<div class=\"values\" id=\"InfoValues\" >");
            _htmlWriter.WriteLine("<table class=\"contentTable\" id=\"infoEventTable\" summary=\"Info Event\" cellspacing=\"2\">");
            _htmlWriter.WriteLine("<thead><tr><th colspan=\"2\">");
            _htmlWriter.WriteLine("Info");
            _htmlWriter.WriteLine("</th></tr></thead>");
            _htmlWriter.WriteLine("<tbody>");
            _htmlWriter.WriteLine("<tr>");
            _htmlWriter.WriteLine(
                  "<th width=\"25%\" > Category: </th><td>" + _event.CategoryEvent
                + "</td></tr><tr><th width=\"25%\" > Location: </th><td>" + _event.Location
                + "</td></tr><tr><th width=\"25%\" > Type: </th><td>" + _event.Type
                + "</td></tr><tr><th width=\"25%\" > Start Date: </th><td>" + _event.StartEv
                + "</td></tr><tr><th width=\"25%\" > End date: </th><td>" + _event.EndEv
                + "</td></tr><tr><th width=\"25%\"> End Date Registry: </th><td>" + _event.EndReg
                + "</td></tr><tr><th width=\"25%\"> Poolbase: </th><td>" + _event.PoolBase
                + "</td></tr><tr><th width=\"25%\"> Limit Time: </th><td>" + _event.LimitTime
                + "</td></tr><tr><th width=\"25%\"> Lanes: </th><td>" + _event.Lanes
                );
            _htmlWriter.WriteLine("</td></tr></tbody></table></div>");

            _htmlWriter.WriteLine("<div class=\"values\" id=\"JuryValues\" >");
            _htmlWriter.WriteLine("<table class=\"contentTable\" id=\"JuryTable\" summary=\"Jury\" cellspacing=\"2\">");
            _htmlWriter.WriteLine("<thead><tr><th colspan=\"2\">");
            _htmlWriter.WriteLine("Jury");
            _htmlWriter.WriteLine("</th></tr></thead>");
            _htmlWriter.WriteLine("<tbody>");
            _htmlWriter.WriteLine("<tr>");
            _htmlWriter.WriteLine(
                  "<th width=\"25%\" > Referee: </th><td>" + _event.Referee
                + "</td></tr><tr><th width=\"25%\" > Coadjuctor: </th><td>" + _event.Coadjuctor
                + "</td></tr><tr><th width=\"25%\" > Depjudge: </th><td>" + _event.Depjudge
                + "</td></tr><tr><th width=\"25%\" > False start Employee: </th><td>" + _event.FSEmpl
                + "</td></tr><tr><th width=\"25%\" > Competition Employee: </th><td>" + _event.CompEmpl
                );
            _htmlWriter.WriteLine("</td></tr></tbody></table></div>");

            _htmlWriter.WriteLine("<div class=\"values\" id=\"CronoValues\" >");
            _htmlWriter.WriteLine("<table class=\"contentTable\" id=\"CronoTable\" summary=\"Crono\" cellspacing=\"2\">");
            _htmlWriter.WriteLine("<thead><tr><th colspan=\"2\">");
            _htmlWriter.WriteLine("Crono");
            _htmlWriter.WriteLine("</th></tr></thead>");
            _htmlWriter.WriteLine("<tbody>");
            _htmlWriter.WriteLine("<tr>");
            _htmlWriter.WriteLine(
                  "<th width=\"25%\" > Type: </th><td>" + _event.CronoType
                + "</td></tr><tr><th width=\"25%\" > Service: </th><td>" + _event.CronoServ
                + "</td></tr><tr><th width=\"25%\" > Society: </th><td>" + _event.CronoSociety
                );
            _htmlWriter.WriteLine("</td></tr></tbody></table></div>");

            _htmlWriter.WriteLine("<div class=\"values\" id=\"OtherValues\" >");
            _htmlWriter.WriteLine("<table class=\"contentTable\" id=\"OtherTable\" summary=\"Other\" cellspacing=\"2\">");
            _htmlWriter.WriteLine("<thead><tr><th colspan=\"2\">");
            _htmlWriter.WriteLine("Other");
            _htmlWriter.WriteLine("</th></tr></thead>");
            _htmlWriter.WriteLine("<tbody>");
            _htmlWriter.WriteLine("<tr>");
            _htmlWriter.WriteLine(
                  "<th width=\"25%\" > Speaker: </th><td>" + _event.Speaker
                + "</td></tr><tr><th width=\"25%\" > Doctor: </th><td>" + _event.Doctor
                + "</td></tr><tr><th width=\"25%\" > Manager: </th><td>" + _event.Manager
                );
            _htmlWriter.WriteLine("</td></tr></tbody></table></div>");

            _htmlWriter.WriteLine("<div class=\"values\" id=\"ProgramValues\" style=\"\">");
            _htmlWriter.WriteLine("<table class=\"contentTable\" id=\"ProgramTable\" summary=\"Other\" cellspacing=\"2\">");
            _htmlWriter.WriteLine("<thead><tr><th colspan=\"4\">");
            _htmlWriter.WriteLine("Program");
            _htmlWriter.WriteLine("</th></tr></thead>");
            _htmlWriter.WriteLine("<tbody>");
            _htmlWriter.WriteLine("<tr>");
            for (int i = 0; i < _event.ProgramList.Count; i++)
            {
                _htmlWriter.WriteLine(
                      "<th width=\"25%\" colspan=\"4\">" + _event.ProgramList[i].Date + "</th></tr>");
                for (int j = 0; j < _event.ProgramList[i].CompetitionsOfDay.Count; j++)
                {
                    _htmlWriter.WriteLine("<tr><td><p/></td><th width=\"15%\"> Speciality: </th><td colspan=\"2\">"
                        + _event.ProgramList[i].CompetitionsOfDay[j].Spec
                        + "</td></tr><tr><td><p/></td><td><p/></td><th width=\"25%\" > Hour: </th><td>"
                        + _event.ProgramList[i].CompetitionsOfDay[j].Hour
                        + "</td></tr><tr><td><p/></td><td><p/></td><th width=\"25%\" > Category: </th><td>"
                        + _event.ProgramList[i].CompetitionsOfDay[j].Category
                        + "</td></tr><tr><td><p/></td><td><p/></td><th width=\"25%\" > Turn: </th><td>"
                        + _event.ProgramList[i].CompetitionsOfDay[j].Turn
                  );
                }
            }
            _htmlWriter.WriteLine("</td></tr></tbody></table></div>");

            _htmlWriter.WriteLine("<div class=\"values\" id=\"StartlistValues\" style=\"\">");
            _htmlWriter.WriteLine("<table class=\"contentTable\" id=\"StartlistTable\" summary=\"Startlist\" cellspacing=\"2\">");
            _htmlWriter.WriteLine("<thead><tr><th colspan=\"3\">");
            _htmlWriter.WriteLine("Startlist");
            _htmlWriter.WriteLine("</th></tr></thead>");
            _htmlWriter.WriteLine("<tbody>");
            _htmlWriter.WriteLine("<tr>");
            for (int i = 0; i < _event.StartList.Count; i++)
            {
                _htmlWriter.WriteLine(
                      "<th colspan=\"3\">" + _event.StartList[i].NameSingleComp + "</th></tr>");
                for (int j = 0; j < _event.StartList[i].StartL.Count; j++)
                {
                    _htmlWriter.WriteLine("<tr><td><p/></td><th colspan=\"2\">"
                        + _event.StartList[i].StartL[j].NameTurn + " " + _event.StartList[i].StartL[j].NumeberTurn
                        + "</th></tr>");
                    for (int k = 0; k < _event.StartList[i].StartL[j].Athlete.Count; k++)
                    {
                        _htmlWriter.WriteLine("<tr><td><p/></td><th>"
                        + _event.StartList[i].StartL[j].Athlete[k].Lane
                        + "</th><td>"
                        + _event.StartList[i].StartL[j].Athlete[k].Code + "<br/>"
                        + _event.StartList[i].StartL[j].Athlete[k].Surname + "<br/>"
                        + _event.StartList[i].StartL[j].Athlete[k].Name + "<br/>"
                        + _event.StartList[i].StartL[j].Athlete[k].Society + "<br/>"
                        + _event.StartList[i].StartL[j].Athlete[k].Birthday + "<br/>Time: "
                        + _event.StartList[i].StartL[j].Athlete[k].TimeRegistry + "<br/>"
                        + "</td></tr>");
                    }
                }
            }

            _htmlWriter.WriteLine("</tbody></table></div>");

            _htmlWriter.WriteLine("<div class=\"values\" id=\"NoteValues\" >");
            _htmlWriter.WriteLine("<table class=\"contentTable\" id=\"NoteTable\" summary=\"Crono\" cellspacing=\"2\">");
            _htmlWriter.WriteLine("<thead><tr><th colspan=\"2\">");
            _htmlWriter.WriteLine("Note");
            _htmlWriter.WriteLine("</th></tr></thead>");
            _htmlWriter.WriteLine("<tbody>");
            _htmlWriter.WriteLine("<tr><td>" + _event.Note);
            _htmlWriter.WriteLine("</td></tr></tbody></table></div>");

            _htmlWriter.WriteLine("</div></body>");
            _htmlWriter.WriteLine("</html>");
            _htmlWriter.Close();

            System.Diagnostics.Process proc = new System.Diagnostics.Process();
            proc.StartInfo.FileName = "HTMLEvent.html";
            proc.StartInfo.UseShellExecute = true;
            proc.Start();
        }


        public void Visit(StartListNode node)
        {
            foreach (ASTNode childNode in node.Children)
            {
                childNode.Accept(this);
            }
        }


        public void Visit(JuryNode node)
        {
            foreach (ASTNode childNode in node.Children)
            {
                childNode.Accept(this);
            }


        }

        public void Visit(OtherNode node)
        {
            foreach (ASTNode childNode in node.Children)
            {
                childNode.Accept(this);
            }
        }

        public void Visit(ProgNode node)
        {
            foreach (ASTNode childNode in node.Children)
            {
                childNode.Accept(this);
            }
        }


        public void Visit(TimingNode node)
        {
            foreach (ASTNode childNode in node.Children)
            {
                childNode.Accept(this);
            }
        }
    }
}
